#include "graphics.h"
#include "avi.h"
#include "graphics_util.h"
#include "image_cache.h"
#include "image.h"
#include "util/mmgr.h"		// Needs to come in early
#include "util/log.h"
#include "util/common_macros.h"
#include <cassert>

Graphics* Graphics::s_pGraphics = 0;
int		  Graphics::s_PixelOffsetX = 0;
int		  Graphics::s_PixelOffsetY = 0;
Graphics::Vertex2D*	Graphics::GetTempVert()
{
#ifdef _PLATFORM_WII
	static unsigned int Size = MAX_TEMP_VERT * sizeof(Graphics::Vertex2D);
	static Graphics::Vertex2D*	VertA = (Graphics::Vertex2D*)WiiMMGR_ScratchPad();
#else
	static Graphics::Vertex2D*	VertA = new Graphics::Vertex2D[MAX_TEMP_VERT];
#endif
	return VertA;
}

unsigned short*		Graphics::GetTempIdx()
{
#ifdef _PLATFORM_WII
	// frequently used together with the TempVertex, so make sure we don't step on each other's toes
	static unsigned int Size = MAX_TEMP_INDEX * sizeof(unsigned short);
	static	unsigned short*		IndexA = (unsigned short*)((unsigned int)WiiMMGR_ScratchPad() + (MAX_TEMP_VERT * sizeof(Graphics::Vertex2D)));
#else
	static	unsigned short*		IndexA = new unsigned short[MAX_TEMP_INDEX];
#endif
	return IndexA;
}

Graphics::Graphics() :
	m_ScreenWidth(0),
	m_ScreenHeight(0),
	m_WindowX(-1),
	m_WindowY(-1),
	m_GraphicsClass(GRAPHICS_CLASS_DX9),
	m_IsWindowed(false),
	m_Filter2D(false),
	m_FrameID(0),
	m_OrgPixelX(0),
	m_OrgPixelY(0),
	m_EnableMipmaps(false),
	m_pForceTexture(0),
	m_PolygonC(0),
	m_BatchC(0)
{

}

Graphics::~Graphics()
{

}

bool	Graphics::Resize(unsigned int Width, unsigned int Height)
{
	m_ScreenWidth	= Width;
	m_ScreenHeight	= Height;

	GraphicsUtil::SetWindowSize(Width, Height);

	return true;
}

void	Graphics::SetupAdditiveAlpha(bool b)
{
	if (b)
	{
#ifdef _PLATFORM_WII
		GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_NOOP );
#else
		SetRenderState( Graphics::RS_ALPHA_TEST, false );
		SetRenderState( Graphics::RS_SRC_BLEND,  Graphics::RV_BLEND_SRC_ALPHA );
		SetRenderState( Graphics::RS_DST_BLEND,  Graphics::RV_BLEND_ONE );
#endif
	} else
	{
#ifdef _PLATFORM_WII
		GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP );
#else
		SetRenderState( Graphics::RS_ALPHA_TEST, true );
		SetRenderState( Graphics::RS_SRC_BLEND,  Graphics::RV_BLEND_SRC_ALPHA );
		SetRenderState( Graphics::RS_DST_BLEND,  Graphics::RV_BLEND_INVSRC_ALPHA );
#endif
	}
}
void	Graphics::RenderBorders()
{
	Graphics::Vertex2D*		VertA = GetGraphics()->GetTempVert();	// max 4 quads
	int		VertI = 0;
	
	COLOR	c = ColorRGBA(0, 0, 0, 255);
	if (s_PixelOffsetX>0)
	{
	// left
		VertA[VertI++].FillRaw(0,				0, c, 0, 0);
		VertA[VertI++].FillRaw(s_PixelOffsetX,	0, c, 0, 0);
		VertA[VertI++].FillRaw(s_PixelOffsetX,  m_ScreenHeight, c, 0, 0);
		VertA[VertI++].FillRaw(0,				0, c, 0, 0);
		VertA[VertI++].FillRaw(s_PixelOffsetX,  m_ScreenHeight, c, 0, 0);
		VertA[VertI++].FillRaw(0,				m_ScreenHeight, c, 0, 0);

	// right
		VertA[VertI++].FillRaw(m_ScreenWidth+s_PixelOffsetX,				0, c, 0, 0);
		VertA[VertI++].FillRaw(m_ScreenWidth+(s_PixelOffsetX*2),	0, c, 0, 0);
		VertA[VertI++].FillRaw(m_ScreenWidth+(s_PixelOffsetX*2),  m_ScreenHeight, c, 0, 0);
		VertA[VertI++].FillRaw(m_ScreenWidth+s_PixelOffsetX,				0, c, 0, 0);
		VertA[VertI++].FillRaw(m_ScreenWidth+(s_PixelOffsetX*2),  m_ScreenHeight, c, 0, 0);
		VertA[VertI++].FillRaw(m_ScreenWidth+s_PixelOffsetX,  m_ScreenHeight, c, 0, 0);
	}
	if (s_PixelOffsetY>0)
	{
		VertA[VertI++].FillRaw(s_PixelOffsetX,	0, c, 0, 0);
		VertA[VertI++].FillRaw(m_ScreenWidth+s_PixelOffsetX,	0, c, 0, 0);
		VertA[VertI++].FillRaw(m_ScreenWidth+s_PixelOffsetX,  s_PixelOffsetY, c, 0, 0);
		VertA[VertI++].FillRaw(s_PixelOffsetX,	0, c, 0, 0);
		VertA[VertI++].FillRaw(m_ScreenWidth+s_PixelOffsetX,  s_PixelOffsetY, c, 0, 0);
		VertA[VertI++].FillRaw(s_PixelOffsetX,	s_PixelOffsetY, c, 0, 0);
	}
	if (VertI > 0)
	{
		SetTexture(0, NULL);
		DrawVertex2D(VertA, VertI);
	}

}

void	Graphics::TakeScreenShot(const std::string& file_name, bool Minimize)
{
	m_ScreenshotFile = file_name;
	m_ScreenshotMinimize = Minimize;
}

Graphics* GetGraphics()
{
	int j=0;
//	assert(Graphics::GetGraphics() && "No Graphics instatiated");
	return Graphics::GetGraphics();
}

void		Graphics::SHUTDOWN()
{
	if (s_pGraphics)
	{
		s_pGraphics->Shutdown();
		
		delete s_pGraphics;
		s_pGraphics = NULL;
	}
}

void	Graphics::AddImageCache(ImageCache* pCache)
{
	DropImageCache(pCache);	// ensure it doesn't already exist
	m_ImageCaches.push_back(pCache);
}

void	Graphics::DropImageCache(ImageCache* pCache)
{
	for (unsigned int i=0; i<m_ImageCaches.size(); i++)
	{
		if (m_ImageCaches[i]==pCache)
		{
			m_ImageCaches.erase(m_ImageCaches.begin() + i);
			return;
		}
	}
}
void	Graphics::SetOriginalPixelOffset(int x, int y)
{
	m_OrgPixelX = x;
	m_OrgPixelY = y;
}

void	Graphics::GetOriginalPixelOffset(int &x, int& y)
{
	x = m_OrgPixelX;
	y = m_OrgPixelY;
}


void	Graphics::Flush()
{
	for (unsigned int i=0; i<m_ImageCaches.size(); i++)
	{
		m_ImageCaches[i]->Flush();
	}
	for (unsigned int i=0; i<m_ActiveMovies.size(); i++)
	{
		m_ActiveMovies[i]->Flush();
	}
}

void	Graphics::Recreate()
{
	for (unsigned int i=0; i<m_ImageCaches.size(); i++)
	{
		m_ImageCaches[i]->Recreate();
	}
	for (unsigned int i=0; i<m_ActiveMovies.size(); i++)
	{
		m_ActiveMovies[i]->Recreate();
	}
}

